# -*- coding: utf-8 -*-
"""
输入框组件
实现文本输入、光标显示、选择和复制粘贴功能
"""

import pygame
import time
from typing import Optional, Callable
from gui.components.base_component import BaseComponent
from gui.styles.colors import get_theme_color, get_current_theme
from gui.styles.fonts import get_font, render_text


class InputBox(BaseComponent):
    """
    文本输入框组件
    支持文本输入、光标显示、文本选择和复制粘贴
    """
    
    def __init__(self, x: int, y: int, width: int, height: int, 
                 placeholder: str = "", max_length: int = 1000):
        """
        初始化输入框
        
        Args:
            x (int): X坐标
            y (int): Y坐标
            width (int): 宽度
            height (int): 高度
            placeholder (str): 占位符文本
            max_length (int): 最大字符长度
        """
        super().__init__(x, y, width, height)
        
        # 文本相关属性
        self.text = ""
        self.placeholder = placeholder
        self.max_length = max_length
        
        # 光标相关属性
        self.cursor_pos = 0
        self.cursor_visible = True
        self.cursor_blink_time = 0.5  # 光标闪烁间隔（秒）
        self.last_blink_time = time.time()
        
        # 选择相关属性
        self.selection_start = 0
        self.selection_end = 0
        self.has_selection = False
        
        # 滚动相关属性
        self.scroll_offset = 0
        self.padding = 8
        
        # 字体设置
        self.font = get_font("input")
        
        # 验证相关
        self.validator: Optional[Callable[[str], bool]] = None
        self.is_valid = True
        
        # 事件回调
        self.on_text_changed: Optional[Callable[[str], None]] = None
        self.on_enter: Optional[Callable[[str], None]] = None
    
    def set_text(self, text: str):
        """设置文本内容"""
        old_text = self.text
        self.text = text[:self.max_length]
        self.cursor_pos = min(self.cursor_pos, len(self.text))
        self.clear_selection()
        self._validate_text()
        self._update_scroll()
        
        if old_text != self.text and self.on_text_changed:
            self.on_text_changed(self.text)
    
    def get_text(self) -> str:
        """获取文本内容"""
        return self.text
    
    def clear(self):
        """清空文本"""
        self.set_text("")
    
    def set_placeholder(self, placeholder: str):
        """设置占位符文本"""
        self.placeholder = placeholder
    
    def set_validator(self, validator: Callable[[str], bool]):
        """设置文本验证器"""
        self.validator = validator
        self._validate_text()
    
    def _validate_text(self):
        """验证文本内容"""
        if self.validator:
            self.is_valid = self.validator(self.text)
        else:
            self.is_valid = True
    
    def _insert_text(self, text: str):
        """在光标位置插入文本"""
        if self.has_selection:
            self._delete_selection()
        
        # 检查长度限制
        available_length = self.max_length - len(self.text)
        if available_length <= 0:
            return
        
        insert_text = text[:available_length]
        self.text = (self.text[:self.cursor_pos] + 
                    insert_text + 
                    self.text[self.cursor_pos:])
        self.cursor_pos += len(insert_text)
        
        self._validate_text()
        self._update_scroll()
        
        if self.on_text_changed:
            self.on_text_changed(self.text)
    
    def _delete_char(self, forward: bool = False):
        """删除字符"""
        if self.has_selection:
            self._delete_selection()
            return
        
        if forward:  # Delete键
            if self.cursor_pos < len(self.text):
                self.text = (self.text[:self.cursor_pos] + 
                           self.text[self.cursor_pos + 1:])
        else:  # Backspace键
            if self.cursor_pos > 0:
                self.text = (self.text[:self.cursor_pos - 1] + 
                           self.text[self.cursor_pos:])
                self.cursor_pos -= 1
        
        self._validate_text()
        self._update_scroll()
        
        if self.on_text_changed:
            self.on_text_changed(self.text)
    
    def _move_cursor(self, delta: int, select: bool = False):
        """移动光标"""
        new_pos = max(0, min(len(self.text), self.cursor_pos + delta))
        
        if select:
            if not self.has_selection:
                self.selection_start = self.cursor_pos
                self.has_selection = True
            self.selection_end = new_pos
        else:
            self.clear_selection()
        
        self.cursor_pos = new_pos
        self._update_scroll()
    
    def _update_scroll(self):
        """更新滚动偏移"""
        if not self.text:
            self.scroll_offset = 0
            return
        
        # 计算光标位置的像素坐标
        cursor_text = self.text[:self.cursor_pos]
        cursor_width = self.font.get_size(cursor_text)[0]
        
        # 可视区域宽度
        visible_width = self.width - 2 * self.padding
        
        # 调整滚动偏移确保光标可见
        if cursor_width - self.scroll_offset < 0:
            self.scroll_offset = cursor_width
        elif cursor_width - self.scroll_offset > visible_width:
            self.scroll_offset = cursor_width - visible_width
    
    def clear_selection(self):
        """清除选择"""
        self.has_selection = False
        self.selection_start = 0
        self.selection_end = 0
    
    def _delete_selection(self):
        """删除选中的文本"""
        if not self.has_selection:
            return
        
        start = min(self.selection_start, self.selection_end)
        end = max(self.selection_start, self.selection_end)
        
        self.text = self.text[:start] + self.text[end:]
        self.cursor_pos = start
        self.clear_selection()
    
    def _get_selected_text(self) -> str:
        """获取选中的文本"""
        if not self.has_selection:
            return ""
        
        start = min(self.selection_start, self.selection_end)
        end = max(self.selection_start, self.selection_end)
        return self.text[start:end]
    
    def _copy_to_clipboard(self):
        """复制选中文本到剪贴板"""
        selected_text = self._get_selected_text()
        if selected_text:
            try:
                # 使用tkinter实现剪贴板功能
                import tkinter as tk
                root = tk.Tk()
                root.withdraw()  # 隐藏窗口
                root.clipboard_clear()
                root.clipboard_append(selected_text)
                root.update()  # 确保剪贴板更新
                root.destroy()
            except Exception as e:
                print(f"复制到剪贴板失败: {e}")
    
    def _paste_from_clipboard(self):
        """从剪贴板粘贴文本"""
        try:
            # 使用tkinter实现剪贴板功能
            import tkinter as tk
            root = tk.Tk()
            root.withdraw()  # 隐藏窗口
            clipboard_text = root.clipboard_get()
            root.destroy()
            
            if clipboard_text:
                # 删除选中的文本（如果有）
                if self.has_selection:
                    self._delete_selection()
                
                # 插入剪贴板文本
                self._insert_text(clipboard_text)
        except Exception as e:
            print(f"从剪贴板粘贴失败: {e}")
    
    def handle_event(self, event: pygame.event.Event) -> bool:
        """处理事件"""
        if not self.visible or not self.enabled:
            return False
        
        # 调用父类事件处理
        if super().handle_event(event):
            return True
        
        if not self.focused:
            return False
        
        # 处理键盘事件
        if event.type == pygame.KEYDOWN:
            keys = pygame.key.get_pressed()
            ctrl_pressed = keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]
            shift_pressed = keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]
            
            if event.key == pygame.K_RETURN or event.key == pygame.K_KP_ENTER:
                if self.on_enter:
                    self.on_enter(self.text)
                return True
            
            elif event.key == pygame.K_BACKSPACE:
                self._delete_char(forward=False)
                return True
            
            elif event.key == pygame.K_DELETE:
                self._delete_char(forward=True)
                return True
            
            elif event.key == pygame.K_LEFT:
                self._move_cursor(-1, shift_pressed)
                return True
            
            elif event.key == pygame.K_RIGHT:
                self._move_cursor(1, shift_pressed)
                return True
            
            elif event.key == pygame.K_HOME:
                delta = -self.cursor_pos
                self._move_cursor(delta, shift_pressed)
                return True
            
            elif event.key == pygame.K_END:
                delta = len(self.text) - self.cursor_pos
                self._move_cursor(delta, shift_pressed)
                return True
            
            elif ctrl_pressed and event.key == pygame.K_a:
                # 全选
                self.selection_start = 0
                self.selection_end = len(self.text)
                self.has_selection = len(self.text) > 0
                return True
            
            elif ctrl_pressed and event.key == pygame.K_c:
                # 复制
                self._copy_to_clipboard()
                return True
            
            elif ctrl_pressed and event.key == pygame.K_v:
                # 粘贴
                self._paste_from_clipboard()
                return True
            
            elif ctrl_pressed and event.key == pygame.K_x:
                # 剪切
                self._copy_to_clipboard()
                self._delete_selection()
                return True
        
        elif event.type == pygame.TEXTINPUT:
            # 处理文本输入
            self._insert_text(event.text)
            return True
        
        return False
    
    def update(self, dt: float):
        """更新组件状态"""
        super().update(dt)
        
        # 更新光标闪烁
        current_time = time.time()
        if current_time - self.last_blink_time >= self.cursor_blink_time:
            self.cursor_visible = not self.cursor_visible
            self.last_blink_time = current_time
    
    def draw(self, surface: pygame.Surface):
        """绘制输入框"""
        if not self.visible:
            return
        
        theme = get_current_theme()
        
        # 确定边框颜色
        if not self.is_valid:
            border_color = theme['error']
        elif self.focused:
            border_color = theme['accent']
        else:
            border_color = get_theme_color('text_secondary')
        
        # 绘制背景
        bg_color = theme['background'] if self.enabled else theme['panel_bg']
        pygame.draw.rect(surface, bg_color, self.rect)
        
        # 绘制边框
        border_width = 2 if self.focused else 1
        pygame.draw.rect(surface, border_color, self.rect, border_width)
        
        # 计算文本绘制区域
        text_rect = pygame.Rect(
            self.x + self.padding,
            self.y + self.padding,
            self.width - 2 * self.padding,
            self.height - 2 * self.padding
        )
        
        # 设置裁剪区域
        surface.set_clip(text_rect)
        
        # 绘制文本或占位符
        if self.text or self.focused:
            text_color = theme['text_primary'] if self.enabled else theme['text_secondary']
            
            # 绘制选择背景
            if self.has_selection and self.focused:
                self._draw_selection(surface, text_rect)
            
            # 绘制文本
            if self.text:
                text_surface = self.font.render(self.text, True, text_color)
                text_x = text_rect.x - self.scroll_offset
                text_y = text_rect.y + (text_rect.height - text_surface.get_height()) // 2
                surface.blit(text_surface, (text_x, text_y))
            
            # 绘制光标
            if self.focused and self.cursor_visible:
                self._draw_cursor(surface, text_rect)
        
        elif self.placeholder:
            # 绘制占位符
            placeholder_color = theme['text_secondary']
            placeholder_surface = self.font.render(self.placeholder, True, placeholder_color)
            placeholder_x = text_rect.x
            placeholder_y = text_rect.y + (text_rect.height - placeholder_surface.get_height()) // 2
            surface.blit(placeholder_surface, (placeholder_x, placeholder_y))
        
        # 取消裁剪
        surface.set_clip(None)
    
    def _draw_selection(self, surface: pygame.Surface, text_rect: pygame.Rect):
        """绘制文本选择背景"""
        if not self.has_selection:
            return
        
        start = min(self.selection_start, self.selection_end)
        end = max(self.selection_start, self.selection_end)
        
        # 计算选择区域的像素位置
        start_text = self.text[:start]
        end_text = self.text[:end]
        
        start_width = self.font.get_size(start_text)[0] if start_text else 0
        end_width = self.font.get_size(end_text)[0] if end_text else 0
        
        selection_x = text_rect.x + start_width - self.scroll_offset
        selection_width = end_width - start_width
        
        # 绘制选择背景
        selection_rect = pygame.Rect(
            selection_x,
            text_rect.y,
            selection_width,
            text_rect.height
        )
        
        theme = get_current_theme()
        selection_color = (*theme['accent'][:3], 100)  # 半透明
        
        # 创建半透明表面
        selection_surface = pygame.Surface((selection_width, text_rect.height), pygame.SRCALPHA)
        selection_surface.fill(selection_color)
        surface.blit(selection_surface, (selection_x, text_rect.y))
    
    def _draw_cursor(self, surface: pygame.Surface, text_rect: pygame.Rect):
        """绘制光标"""
        cursor_text = self.text[:self.cursor_pos]
        cursor_width = self.font.get_size(cursor_text)[0] if cursor_text else 0
        
        cursor_x = text_rect.x + cursor_width - self.scroll_offset
        cursor_y = text_rect.y + 2
        cursor_height = text_rect.height - 4
        
        theme = get_current_theme()
        cursor_color = theme['text_primary']
        
        pygame.draw.line(surface, cursor_color, 
                        (cursor_x, cursor_y), 
                        (cursor_x, cursor_y + cursor_height), 2)